package com.apes.framework.jpa.comment;

import com.apes.framework.jpa.ClassWrapper;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.soe.annotations.Business;
import com.apes.framework.plugin.soe.annotations.States;
import com.apes.framework.util.JpaUtil;
import com.apes.framework.util.ReflectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;

/**
 * 功能：comment 服务
 *
 * @author xul
 * @create 2018-11-02 16:14
 */
@Service("commentService")
public class CommentService {

    private static List<String> tables = new ArrayList<>();

    @Value("${spring.jpa.generate-ddl:false}")
    private boolean generateDDL;

    /***
     * 批量更新表备注
     */
    public void insertComment(SimpleRequest request) {
        JpaUtil.getAllDomainType().forEach(domainTypeName -> {
            Class domainType = ReflectUtil.getClass(domainTypeName);
            getEntity(domainType);
        });
    }


    /**
     * 监听Model遍历事件
     **/
    @Transactional(rollbackFor = Exception.class)
//    @Listener(topic = EventConst.EVENT_MODEL_READ) //暂时先不处理备注
    public void onModelRead(SimpleRequest request) {
        if (!generateDDL) return;
        try {
            ClassWrapper wrapper = (ClassWrapper) request.getData();
            if (tables.stream().filter(table -> table.equals(wrapper.getClazz().getName())).count() > 0) return;
            tables.add(wrapper.getClazz().getName());
            getEntity(wrapper.getClazz());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getEntity(Class entityClazz) {
        Table table = ReflectUtil.getAnnotation(entityClazz, Table.class);
        if (table == null) return;
        String tableName = StringUtils.isEmpty(table.name()) ? entityClazz.getSimpleName() : table.name();

        String tableComment = null;
        /**存在Business注解**/
        Business business = ReflectUtil.getAnnotation(entityClazz, Business.class);
        if (business != null) {
            tableComment = business.value();
        }

        PropertyDescriptor[] descriptors = ReflectUtil.getPropertyDescriptors(entityClazz);
        if (descriptors == null) return;
        for (PropertyDescriptor descriptor : descriptors) {
            if (StringUtils.isEmpty(tableComment)) {
                ApesGenerator generator = ReflectUtil.getAnnotation(entityClazz, descriptor.getName(), ApesGenerator.class);
                if (generator != null) {
                    tableComment = generator.name();
                }
            }

            String columnName, value;
            value = getColumnDescription(entityClazz, descriptor);
            if (StringUtils.isEmpty(value)) continue;

            Column column = ReflectUtil.getAnnotation(entityClazz, descriptor.getName(), Column.class);
            columnName = column != null ? StringUtils.isEmpty(column.name()) ? descriptor.getName() : column.name() : null;
            if (StringUtils.isEmpty(columnName)) {
                JoinColumn joinColumn = ReflectUtil.getAnnotation(entityClazz, descriptor.getName(), JoinColumn.class);
                columnName = joinColumn != null ? StringUtils.isEmpty(joinColumn.name()) ? descriptor.getName() : joinColumn.name() : null;
            }
            if (StringUtils.isEmpty(columnName)) continue;

            comment(tableName, columnName, value);
        }

        if (!StringUtils.isEmpty(tableComment)) {
            comment(tableName, tableComment);
        }
    }

    public static String getColumnDescription(Class entityClazz, PropertyDescriptor descriptor) {
        String value;
        Comment comment = ReflectUtil.getAnnotation(entityClazz, descriptor.getName(), Comment.class);
        value = comment != null ? comment.value() : null;
        if (StringUtils.isEmpty(value)) {
            States states = ReflectUtil.getAnnotation(entityClazz, descriptor.getName(), States.class);
            value = states != null ? states.name() : null;
        }
        return value;
    }

    @Autowired
    private EntityManager em;

    private void comment(String tableName, String columnName, String comment) {
        try {
            String sql = String.format("comment on column %s.%s is '%s'", tableName, columnName , comment);
            em.createNativeQuery(sql).executeUpdate();
        } catch (Exception e){
            System.out.print(e);
        }

    }

    private void comment(String tableName, String comment) {
        try {
            String sql = String.format("comment on table %s is '%s'", tableName, comment);
            em.createNativeQuery(sql).executeUpdate();
        } catch (Exception e) {
            System.out.print(e);
        }
    }
}
